package com.globallogic.training.javase.university.schedule;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import com.globallogic.training.javase.university.member.Group;
import com.globallogic.training.javase.university.member.Teacher;
import com.globallogic.training.javase.university.subject.Activity;

/**
 * This class represents the Schedule built for one week.
 * 
 * @author Ivan Moisiienko
 * @version 0.1 2013/04/22
 */
public class Schedule {

	public static final int NUMBER_OF_CELLS_PER_DAY = 6;

	private Set<ScheduleCell> scheduleCells = new TreeSet<ScheduleCell>();

	public Set<ScheduleCell> getSchedule() {
		return scheduleCells;
	}

	public ScheduleCell getCell(DayOfWeek day, int cellNumber, Auditorium aud) {
		if (cellNumber >= 1 && cellNumber <= Schedule.NUMBER_OF_CELLS_PER_DAY) {

			for (Iterator<ScheduleCell> it = scheduleCells.iterator(); it
					.hasNext();) {
				ScheduleCell sc = it.next();
				if (sc.equals(new ScheduleCell(day, cellNumber, aud)))
					return sc;
			}
		}
		return null;
	}

	public boolean scheduleActivity(Activity act, Set<Auditorium> auditoriums) {

		for (DayOfWeek dayOfWeek : DayOfWeek.values()) {
			for (int timeSlot = 1; timeSlot <= Schedule.NUMBER_OF_CELLS_PER_DAY; timeSlot++) {
				for (Auditorium auditorium : auditoriums) {
					ScheduleCell cell = new ScheduleCell(dayOfWeek, timeSlot,
							auditorium);
					cell.setActivity(act);
					if (checkGroupConstraint(cell) && checkTeacherConstraint(cell) 
							&& scheduleCells.add(cell)) {
						return true;
					}
				}
			}
		}

		return false;
	}

	boolean checkGroupConstraint(ScheduleCell cell) {
		Activity activity = cell.getActivityAssigned();
		if (cell != null && activity != null) {
			Group group = activity.getGroup();
			DayOfWeek dayOfWeek = cell.getDay();
			int timeSlot = cell.getCellNumber();

			for (ScheduleCell scheduleCell : scheduleCells) {
				if (scheduleCell != null 
						&& scheduleCell.getDay().equals(dayOfWeek)
						&& scheduleCell.getCellNumber() == timeSlot
						&& scheduleCell.getActivityAssigned().getGroup().equals(group)) {
					return false;
				}
			}
		}		
		return true;
	}
	
	boolean checkTeacherConstraint(ScheduleCell cell) {
		Activity activity = cell.getActivityAssigned();
		if (cell != null && activity != null) {
			Teacher teacher = activity.getTeacher();
			DayOfWeek dayOfWeek = cell.getDay();
			int timeSlot = cell.getCellNumber();
			
			for (ScheduleCell scheduleCell : scheduleCells) {
				if (scheduleCell.getDay().equals(dayOfWeek)
						&& scheduleCell.getCellNumber() == timeSlot
						&& scheduleCell.getActivityAssigned().getTeacher().equals(teacher)) {
					return false;
				}
			}
		}
		return true;
	}

	public Activity getActivity(DayOfWeek day, int cellNumber, Group group) {
		if (cellNumber >= 1 && cellNumber <= Schedule.NUMBER_OF_CELLS_PER_DAY) {

			for (ScheduleCell cell : scheduleCells) {
				if (cell.hasGroup(group) && cell.getDay().equals(day)
						&& cell.getCellNumber() == cellNumber) {
					return cell.getActivityAssigned();
				}
			}
		}

		return null;
	}

	public Auditorium getAuditorium(DayOfWeek day, int cellNumber, Group group) {
		if (cellNumber >= 1 && cellNumber <= Schedule.NUMBER_OF_CELLS_PER_DAY) {

			for (ScheduleCell cell : scheduleCells) {
				if (cell.hasGroup(group) && cell.getDay().equals(day)
						&& cell.getCellNumber() == cellNumber) {
					return cell.getAuditoriumAssigned();
				}
			}
		}

		return null;
	}

}